package cc.yaomm.common.basic.sms;

import cc.yaomm.common.basic.base.SuperSmsTemplate;
import cc.yaomm.common.basic.sms.properties.AliSmsProperties;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * Created by XQL on 2020/5/14.
 * 阿里云短信 服务器
 */
@Slf4j
public class AliSmsService implements SmsService {

    @Autowired
    AliSmsProperties aliSmsProperties;

    //产品名称:云通信短信API产品,开发者无需替换
    static final String product = "Dysmsapi";

    //产品域名,开发者无需替换
    static final String domain = "dysmsapi.aliyuncs.com";

    /**
     * <p>@description 发送短信</p>
     * <p>@author QiLin.Xing</p>
     * <p>@date 2020/5/17 15:03</p>
     * <p>@version 1.0</p>
     *
     * @param phoneNum 手机号
     * @param params   短信参数
     * @param template 模板
     * @return 是否发送成功
     */
    @Override
    public boolean send(String phoneNum, Map<String, Object> params, SuperSmsTemplate template) {
        //白名单过滤
        phoneNum = this.filterWhiteList(phoneNum);
        if (StringUtils.isEmpty(phoneNum)) {
            log.warn("发送短信失败-白名单限制,phoneNum={}", phoneNum);
            //throw new BusinessException("发送短信失败-白名单限制");
            return false;
        }

        try {
            //发送短信
            return this.sendSms(phoneNum, params, template);
        } catch (ClientException e) {
            log.error("发送短信异常", e);
            return false;
        }
    }

    /**
     * <p>@Description: 白名单过滤</p>
     * <p>@Author: QiLin.Xing </p>
     * <p>@Date: 2020/5/17 15:09 </p>
     * <p>@Version: 1.0
     *
     * @param phoneNum 手机号
     * @return
     */
    private String filterWhiteList(String phoneNum) {
        //判断是否设置了白名单
        if (StringUtils.isEmpty(aliSmsProperties.getWhiteList())) {
            return phoneNum;
        }

        String[] phoneNums = phoneNum.split(",");
        //判断是否有多个手机号
        if (phoneNums.length > 1) {
            for (String phone : phoneNums) {
                //判断包含单个手机号
                if (!aliSmsProperties.getWhiteList().contains(phone)) {
                    log.error("发送短信失败-白名单限制；白名单：{}，当前手机号：{}", aliSmsProperties.getWhiteList(), phone);
                    phoneNum = phoneNum.replace(phone, "").replace(",,", ",");
                }
            }

            //判断是否是以逗号结尾
            if (phoneNum.endsWith(",")) {
                phoneNum = phoneNum.substring(0, phoneNum.length() - 1);
            }
            return phoneNum;
        } else {
            //判断白名单中是否包含该手机号
            if (aliSmsProperties.getWhiteList().contains(phoneNum)) {
                return phoneNum;
            } else {
                log.error("发送短信失败-白名单限制；白名单：{}，当前手机号：{}", aliSmsProperties.getWhiteList(), phoneNum);
                return null;
            }
        }
    }

    /**
     * <p>@description 发送短信</p>
     * <p>@author QiLin.Xing</p>
     * <p>@date 2020/5/17 15:03</p>
     * <p>@version 1.0</p>
     *
     * @param phoneNum 手机号
     * @param params   短信参数
     * @param template 模板
     * @return
     * @throws ClientException
     */
    private boolean sendSms(String phoneNum, Map<String, Object> params, SuperSmsTemplate template) throws ClientException {
        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou",
                aliSmsProperties.getAppKey(), aliSmsProperties.getAppSecret());
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象-具体描述见控制台-文档部分内容
        SendSmsRequest request = new SendSmsRequest();
        //必填:待发送手机号
        request.setPhoneNumbers(phoneNum);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName(aliSmsProperties.getSign());
        //必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(template.getCode());
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        if (!CollectionUtils.isEmpty(params)) {
            request.setTemplateParam(JSON.toJSONString(params));
        }

        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
        //request.setSmsUpExtendCode("90997");

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        //request.setOutId("yourOutId");

        //hint 此处可能会抛出异常，注意catch
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

        String returnCode = sendSmsResponse.getCode();
        if ("ok".equalsIgnoreCase(returnCode)) {
            return true;
        } else {
            log.error("发送短信失败：{}", JSON.toJSON(sendSmsResponse));
            return false;
        }
    }
}
